using System.Buffers;
using SuperSocket.ProtoBase;

namespace SuperSocketProxy;

public enum SocketPipeFilterType
{
    Handshake,
    AuthEndPoint,
    AuthUserName,
    ForwardData,
}

/// <summary>
/// +----+-----+-------+------+----------+----------+
/// | 0x06 | body length | 0x06 | 0x00 | 0x02 | 0x00
/// +----+-----+-------+------+----------+----------+
/// </summary>
public sealed class Socket6PipeFilter : FixedHeaderPipelineFilter<SocketProxyPacket>
{
    /// <summary>
    /// 头信息
    /// </summary>
    private const byte Header = 0x06;
    
    /// <summary>
    /// 包头长度
    /// </summary>
    private const byte BodyHeaderLength = 3;
    
    private readonly SocketPipeFilterType _pipeFilter;
    
    private static readonly PacketFactoryPool PacketFactoryPool = new();

    static Socket6PipeFilter()
    {
        PacketFactoryPool.RegisterPacketType<Socket5HandshakePacket>(SocketPipeFilterType.Handshake);
        PacketFactoryPool.RegisterPacketType<Socket5AuthPassPacket>(SocketPipeFilterType.AuthUserName);
        PacketFactoryPool.RegisterPacketType<Socket5EndPointPacket>(SocketPipeFilterType.AuthEndPoint);
        PacketFactoryPool.RegisterPacketType<SocketProxyDataPacket>(SocketPipeFilterType.ForwardData);
    }
    
    public Socket6PipeFilter(SocketPipeFilterType nexFilterType = SocketPipeFilterType.Handshake) 
        : base(BodyHeaderLength)
    {
        _pipeFilter = nexFilterType;
    }

    protected override SocketProxyPacket DecodePackage(ref ReadOnlySequence<byte> buffer)
    {
        var reader = new SequenceReader<byte>(buffer.Slice(BodyHeaderLength));
        
        switch (_pipeFilter)
        {
            case SocketPipeFilterType.Handshake://当前握手完毕设置下一个过滤器为验证密码
                NextFilter = new Socket6PipeFilter(SocketPipeFilterType.AuthUserName);
                break;
            case SocketPipeFilterType.AuthUserName://当前验证密码完毕设置下一个过滤器为验证地址
                NextFilter = new Socket6PipeFilter(SocketPipeFilterType.AuthEndPoint);
                break;
            case SocketPipeFilterType.AuthEndPoint://当前验证地址完毕设置下一个过滤器为转发数据
                NextFilter = new ProxyDataPipeFilter();
                break;
            default:
                break;
        }
        
        var packet = PacketFactoryPool.Create(_pipeFilter);
        
        return packet.Decode(ref reader);
    }

    protected override int GetBodyLengthFromHeader(ref ReadOnlySequence<byte> buffer)
    {
        var reader = new SequenceReader<byte>(buffer);

        reader.TryRead(out var head);

        if (head != Header)
            throw new ProtocolException("头部信息错误");
        
        reader.TryReadBigEndian(out short bodyLength);//读取后2字节 这2个字节包含了尾包的长度
        
        return bodyLength;
    }
}